package com.vinci.pdf.service.impl;

import com.itextpdf.text.Document;
import com.itextpdf.text.Image;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.*;
import com.vinci.pdf.entity.Person;
import com.vinci.pdf.service.api.PdfGenerateTestService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.lang.reflect.Field;
import java.net.URL;
import java.net.URLEncoder;
import java.util.Objects;

/**
 * @package: com.vinci.pdf.service.impl
 * @className: PdfGenerateTestServiceImpl
 * @author: Vinci
 * @description: pdf生成测试接口实现
 * @date: 2023/11/13 10:15
 */
@Service
public class PdfGenerateTestServiceImpl implements PdfGenerateTestService {


    /**
     * @description: 日志服务
     **/
    private static final Logger log = LoggerFactory.getLogger(PdfGenerateTestServiceImpl.class);


    /**
     * @description: pdf生成
     * @author: Vinci
     * @date: 2023/11/13 10:25
     **/
    @Override
    public void pdfGenerate(HttpServletResponse response) throws UnsupportedEncodingException {
        // 模板地址
        URL resource = Thread.currentThread().getContextClassLoader()
                .getResource("templates/aipuu-y1mhx.pdf");
        if(resource == null){
            throw new RuntimeException("没有找到模板");
        }

        String path = resource.getPath();

        // PDF的文件名称 及响应头
        String fileName = "test.pdf";
        fileName = URLEncoder.encode(fileName, "UTF-8");
        response.setContentType("application/force-download");
        //如果想要下载文件的话，这里的inline可以替换为 attachment
        response.setHeader("Content-Disposition",
                "fileName=" + fileName);


        OutputStream ops = null;
        ByteArrayOutputStream bos = null;
        PdfStamper pdfStamper = null;
        PdfReader pdfReader = null;

        try {
            ops = response.getOutputStream();
            pdfReader = new PdfReader(path);
            bos = new ByteArrayOutputStream();

            // 根据模板生成新的PDF
            pdfStamper = new PdfStamper(pdfReader, bos);
            AcroFields form = pdfStamper.getAcroFields();

            // 设置字体
            BaseFont font = BaseFont.createFont(
                    "C:/WINDOWS/Fonts/SIMSUN.TTC,1",
                    BaseFont.IDENTITY_H,
                    BaseFont.EMBEDDED
            );
            form.addSubstitutionFont(font);

            // 获取数据(这里在无参构造中生成了一些数据，实际开发中可用持久化数据来代替)
            Person person = new Person();

            // 通过反射遍历来给PDF中的表单生成数据
            Field[] fields = person.getClass().getDeclaredFields();
            for (Field field : fields) {
                field.setAccessible(true);
                String key = field.getName();
                Object value = field.get(person);
                if(!Objects.equals(key,"largeHeadPhoto")){
                    //处理文本数据
                    form.setField(key, value.toString());
                }else{
                    // 通过表单域名获取所在页和坐标，左下角为起点
                    int pageNo = form.getFieldPositions(key).get(0).page;
                    Rectangle signRect = form.getFieldPositions(key).get(0).position;
                    float x = signRect.getLeft();
                    float y = signRect.getBottom();
                    // 读图片
                    Image image = Image.getInstance(value.toString());
                    // 获取操作的页面
                    PdfContentByte under = pdfStamper.getOverContent(pageNo);
                    // 根据域的大小缩放图片
                    image.scaleToFit(signRect.getWidth(), signRect.getHeight());
                    // 添加图片
                    image.setAbsolutePosition(x, y);
                    under.addImage(image);
                }
            }

            // 设置PDF为只读
            pdfStamper.setFormFlattening(true);

            // 关闭资源
            pdfStamper.close();

            Document doc = new Document();
            PdfCopy copy = new PdfCopy(doc, ops);
            doc.open();
            PdfImportedPage importPage = copy.getImportedPage(new PdfReader(bos.toByteArray()), 1);
            copy.addPage(importPage);
            doc.close();

        }catch (Exception e){
            log.error("发现异常",e);
        }finally {
            try {
                if (ops != null) {
                    ops.flush();
                    ops.close();
                }
                if (pdfReader != null) {
                    pdfReader.close();
                }
            }catch (Exception e){
                log.error("发现异常",e);
            }
        }
    }


}
